﻿#include "SoundInterface.h"

////MMRESULT mmRet = waveInOpen(&m_hWaveIn, /*nDevId*/WAVE_MAPPER, &waveFormat, (DWORD_PTR)WaveInProcFun, (DWORD_PTR)this, CALLBACK_FUNCTION); 
//
////采用回调用的方法，当你异常拔插设备的时候，很容易导致程序死锁  ，
////应改为线程处理 ，弄了一两天，终于搞好了。。。。
//
//
//DWORD threadid;
//HANDLE handle = CreateThread(NULL, 0, RecordProcForKV, this, 0, &threadid);
//
//
////MMRESULT mmRet = waveInOpen(&m_hWaveIn, /*nDevId*/WAVE_MAPPER, &waveFormat, (DWORD_PTR)WaveInProcFun, (DWORD_PTR)this, CALLBACK_FUNCTION); //lint !e620 
//
//
//MMRESULT mmRet = waveInOpen(&m_hWaveIn, /*nDevId*/WAVE_MAPPER, &waveFormat, (DWORD_PTR)threadid, (DWORD_PTR)this, CALLBACK_THREAD); //lint !e620 
//
//DWORD   CSoundIn::RecordProcForKV(LPVOID p)
//{
//	CSoundIn* pSoundIn = (CSoundIn*)p;
//	while (!pSoundIn->IsStop())
//	{
//		MSG msg;
//
//
//		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
//		{
//			if (WIM_DATA == msg.message)
//			{
//				//WAVEHDR* pwh = ( WAVEHDR* )msg.lParam;
//
//
//				//JP_ASSERT(NULL != m_hWaveIn);
//
//
//				LPWAVEHDR pHdr = (LPWAVEHDR)msg.lParam;
//
//
//				if (pHdr->dwBytesRecorded > 0)
//				{
//					if (NULL != pSoundIn->m_funAudioData && !pSoundIn->IsStop())
//					{
//						if (NULL != pSoundIn->m_pSoundTouch)
//						{
//							pSoundIn->m_pSoundTouch->putSamples((soundtouch::SAMPLETYPE*)pHdr->lpData, pHdr->dwBytesRecorded / pSoundIn->m_lBytesPerSample);
//						}
//						else
//						{
//							pSoundIn->m_frameInfo.lRelativeTime = (JP_TimeNow() - pSoundIn->m_lBegainTime);
//
//
//							if (NULL != pSoundIn->m_pAudioFmt)
//							{
//								Uint8* pFrameData = NULL;
//								Sint32 lFrameLen = 0;
//								Sint32 lAudioFrameDuration = 0;
//
//
//								if (NULL != pSoundIn->m_pSpeex)
//								{
//									speex_preprocess_run(pSoundIn->m_pSpeex, (spx_int16_t*)pHdr->lpData);
//								}
//
//
//								if (VID_PLAY_ERROR_SUCCESS == pSoundIn->m_pAudioFmt->CvtAudioSampleEx((Uint8*)pHdr->lpData, (long)pHdr->dwBytesRecorded, pSoundIn->m_frameInfo.lRelativeTime))
//								{
//									do
//									{
//										if (pSoundIn->IsStop())
//										{
//											break;
//										}
//										if (!pSoundIn->m_pAudioFmt->GetCvtData(pFrameData, lFrameLen, pSoundIn->m_frameInfo.lRelativeTime, lAudioFrameDuration))
//										{
//											break;
//										}
//
//
//										pSoundIn->m_funAudioData(pSoundIn->m_frameInfo, pFrameData, lFrameLen, pSoundIn->m_pAudioDataUsrParam);
//										pSoundIn->m_pAudioFmt->RemoveCurFrame();
//
//
//									} while (true); //lint !e506
//								}
//							}
//						}
//					}
//					else if (NULL != pSoundIn->m_funSoundInNotify)
//					{
//						if (!pSoundIn->IsStop())
//							pSoundIn->m_funSoundInNotify((JP_HANDLE)pSoundIn, (Uint8*)pHdr->lpData, (long)pHdr->dwBytesRecorded, pSoundIn->m_pSoundInUsrParam);
//					}
//				}
//
//
//				if (!pSoundIn->IsStop())
//				{
//					waveInAddBuffer(pSoundIn->m_hWaveIn, pHdr, sizeof(WAVEHDR));
//				}
//
//
//
//
//			}
//		}
//
//
//		Sleep(10);
//	}
//
//
//	return 1;
//}

void SoundInterface::win_init(JMutex *t_get_mutex,JMutex *t_put_mutex,RTPQUE *t_get_que,RTPQUE *t_put_que)
{
	m_winsndData = new WinSndData;
	memset(m_winsndData,0,sizeof(WinSndData));
	m_winsndData->m_put_que = t_put_que;
	m_winsndData->m_get_que = t_get_que;
	m_winsndData->m_get_mutex = t_get_mutex;
	m_winsndData->m_put_mutex = t_put_mutex;

	m_winsndData->sound_err = -1;
	m_winsndData->read_stop.Lock();
	m_winsndData->write_stop.Lock();
	m_winsndData->read_started = false;
	m_winsndData->write_started = true;
	m_winsndData->write_stop.Unlock();
	m_winsndData->read_stop.Unlock();	
	m_winsndData->bits = 16;
	m_winsndData->rate = 8000;

	m_winsndData->is_out_ok = false;
	m_winsndData->is_in_ok = false;
	m_winsndData->is_error = false;
	m_winsndData->waveInThreadId = 0;
	m_winsndData->waveOutThreadId = 0;
	m_winsndData->waveInThreadHandle = NULL;
	m_winsndData->waveOutThreadHandle = NULL;
	read_started = false;
	write_started = false;
	isFirstPlay = true;
}

DWORD SoundInterface::SpeakerThreadFun(LPVOID p)
{
	WinSndData* device = (WinSndData *)p;
	while (!device->is_error)
	{
		MSG msg;
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			//printf("SpeakerThreadFun is:%d\n", msg.message);
			switch(msg.message)
			{
			case WOM_OPEN:break;
			case WOM_CLOSE:break;
			case WOM_DONE:
				device->buffer_playing--;
				//printf("buffer playing = %d\n", device->buffer_playing);
				break;
			default:break;
			}
		}
		else
			Sleep(10);
	}
	printf("SpeakerThreadFun\n");
	return 0;
}

DWORD SoundInterface::WaveInThreadFun(LPVOID p)
{
	WAVEHDR *wHdr;
	MMRESULT mr = NOERROR;
	WinSndData* device = (WinSndData *)p;
	while (!device->is_error)
	{
		MSG msg;
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		//if(GetMessage(&msg, NULL, 0, 0))
		{
			//printf("WaveInThreadFun:%x\n", msg.message);
			switch (msg.message)
			{
			case MM_WOM_DONE:
				wHdr = (WAVEHDR *)msg.lParam;
				/* A waveform-audio data block has been played and can now be freed. */
				waveInUnprepareHeader(device->waveindev, (LPWAVEHDR)wHdr, sizeof(WAVEHDR));
				break;
			case WIM_OPEN:
				break;
			case WIM_CLOSE:
				break;
			case WIM_DATA:
				wHdr = (WAVEHDR *)msg.lParam;
				device->read_stop.Lock();
				if (!device->read_started)
				{
					device->read_stop.Unlock();
					printf("read started error\n");
					return 0;
				}
				device->read_stop.Unlock();

				device->read_stop.Lock();
				device->write_stop.Lock();
				if (!device->read_started && !device->write_started)
				{
					mr = waveInUnprepareHeader(device->waveindev, (LPWAVEHDR)wHdr, sizeof (WAVEHDR));
					device->write_stop.Unlock();
					device->read_stop.Unlock();
					printf("waveInUnprepareHeader error\n");
					return 0;
				}
				device->write_stop.Unlock();
				device->read_stop.Unlock();
				//printf("bufflen = %d, recode = %d\n",wHdr->dwBufferLength,wHdr->dwBytesRecorded);
				if (wHdr->dwBufferLength != wHdr->dwBytesRecorded)
				{
					mr = waveInAddBuffer(device->waveindev, wHdr, sizeof(WAVEHDR));
					if (mr != MMSYSERR_NOERROR)
					{
						printf("WaveInCallback : error adding buffer to sound card (waveInAddBuffer:0x%i)", mr);
						device->read_stop.Lock();
						device->write_stop.Lock();
						device->is_error = true;
						device->write_stop.Unlock();
						device->read_stop.Unlock();
					}
					return 0;
				}
				device->read_stop.Lock();
				if (device->read_started)
				{

					/*将音频信息放入RTP缓冲区*/
					RTP_INFO putbuf;
					memset(&putbuf, 0, sizeof(RTP_INFO));
					memcpy(putbuf.DecData, wHdr->lpData, wHdr->dwBufferLength);

					putbuf.PayLoadLen = wHdr->dwBufferLength;
					//printf("get wave from dev payloadlen=%d-------\n",putbuf.PayLoadLen);

					//printf("get wave from dev payloadlen=%d+++++++++++++++++++++++++===========curtimestamp=%ld\n", putbuf.PayLoadLen,GetTickCount());
					if (putbuf.PayLoadLen == 1600)
					{
						device->m_put_mutex->Lock();
						device->m_put_que->push_back(putbuf);
						device->m_put_mutex->Unlock();
					}

				}
				device->read_stop.Unlock();

				mr = waveInAddBuffer(device->waveindev, &(device->waveinhdr[wHdr->dwUser]), sizeof (WAVEHDR));
				if (mr != MMSYSERR_NOERROR)
				{
					printf("WaveInCallback : error adding buffer to sound card (waveInAddBuffer:0x%i)", mr);
					device->read_stop.Lock();
					device->write_stop.Lock();
					device->is_error = true;
					device->write_stop.Unlock();
					device->read_stop.Unlock();
					return 0;
				}
				break;
			default:
				//printf("is not find msgtype:%x\n", msg.message);
				break;
			}
		}
		Sleep(10);
	}
	printf("WaveInThreadFun end\n");
	return 0;
}

void CALLBACK  SoundInterface::SpeakerCallback(HWAVEOUT _waveoutdev, UINT uMsg, DWORD dwInstance,DWORD dwParam1, DWORD dwParam2)
{
	WinSndData *device;
	switch(uMsg)
	{
	case WOM_OPEN:break;
	case WOM_CLOSE:break;
	case WOM_DONE:
		device = (WinSndData*)dwInstance;
		device->buffer_playing--;
		//printf("buffer playing = %d\n",device->buffer_playing);
		break;
	default:break;
	}
}

void CALLBACK  SoundInterface::WaveInCallback(HWAVEIN waveindev, UINT uMsg, DWORD dwInstance,DWORD dwParam1, DWORD dwParam2)
{
		WAVEHDR *wHdr;
  		MMRESULT mr = NOERROR;
		WinSndData *device;
		
		device = (WinSndData *)dwInstance;
		if(device->waveindev != waveindev)
			return;
		//printf("umsg = %d, WOM_DONE = %d, WIM_OPEN = %d, WIM_DATA = %d, WIM_CLOSE = %d\n",uMsg,MM_WOM_DONE,WIM_OPEN,WIM_DATA,WIM_CLOSE);
		switch (uMsg)
		{
      		case MM_WOM_DONE:
				wHdr = (WAVEHDR *) dwParam1;
				/* A waveform-audio data block has been played and can now be freed. */
				waveInUnprepareHeader(device->waveindev, (LPWAVEHDR)wHdr, sizeof(WAVEHDR));
				break;
			case WIM_OPEN:
				break;
			case WIM_CLOSE:
				break;
			case WIM_DATA:
				wHdr = (WAVEHDR *)dwParam1;				
				device->read_stop.Lock();
				if (!device->read_started)
				{
					device->read_stop.Unlock();
					printf("read started error\n");
					return;
				}
				device->read_stop.Unlock();
				
				device->read_stop.Lock();
				device->write_stop.Lock();
				if (!device->read_started && !device->write_started)
				{
					mr = waveInUnprepareHeader(device->waveindev, (LPWAVEHDR)wHdr, sizeof (WAVEHDR));
					device->write_stop.Unlock();
					device->read_stop.Unlock();
					printf("waveInUnprepareHeader error\n");
					return;
				}
				device->write_stop.Unlock();
				device->read_stop.Unlock();
				printf("bufflen = %d, recode = %d\n",wHdr->dwBufferLength,wHdr->dwBytesRecorded);
				if (wHdr->dwBufferLength!=wHdr->dwBytesRecorded)
				{
					mr = waveInAddBuffer(device->waveindev,wHdr,sizeof(WAVEHDR));
					if (mr != MMSYSERR_NOERROR)
					{
						printf("WaveInCallback : error adding buffer to sound card (waveInAddBuffer:0x%i)", mr); 
						device->read_stop.Lock();
						device->write_stop.Lock();
						device->is_error = true;
						device->write_stop.Unlock();
						device->read_stop.Unlock();
					}
					return;
				}			
				device->read_stop.Lock();
				if (device->read_started)
				{
					
					/*将音频信息放入RTP缓冲区*/
					RTP_INFO putbuf;
					memset(&putbuf, 0, sizeof(RTP_INFO));	
					memcpy(putbuf.DecData,wHdr->lpData, wHdr->dwBufferLength);
					
					putbuf.PayLoadLen = wHdr->dwBufferLength;	
					printf("get wave from dev payloadlen=%d-------\n",putbuf.PayLoadLen);

					//printf("get wave from dev payloadlen=%d+++++++++++++++++++++++++===========curtimestamp=%ld\n", putbuf.PayLoadLen,GetTickCount());
					if(putbuf.PayLoadLen==1600)
					{
						device->m_put_mutex->Lock();
						device->m_put_que->push_back(putbuf);
						device->m_put_mutex->Unlock();
					}
					
				}
				device->read_stop.Unlock();
				
				mr = waveInAddBuffer(device->waveindev,&(device->waveinhdr[wHdr->dwUser]), sizeof (WAVEHDR));
				if (mr != MMSYSERR_NOERROR)
				{
					printf("WaveInCallback : error adding buffer to sound card (waveInAddBuffer:0x%i)", mr);
					device->read_stop.Lock();
					device->write_stop.Lock();
					device->is_error = true;
					device->write_stop.Unlock();
					device->read_stop.Unlock();
					return;
				}
    	}
}

int  SoundInterface::open_dev(WinSndData *device, int bits, int stereo, int rate, int *minsz, SoundInterface *pSound)
{
   	MMRESULT mr = NOERROR;
	DWORD dwFlag;
	int i;
	int channel = 1;
	if (stereo>0)
		channel = stereo; 
	//printf("stereo = %d channel=%d\n", stereo, channel);
	device->wfx.wFormatTag = WAVE_FORMAT_PCM;
	device->wfx.cbSize = 0;
	device->wfx.nAvgBytesPerSec = 16000;
	device->wfx.nBlockAlign = 2;
	device->wfx.nChannels = channel;
	device->wfx.nSamplesPerSec = rate; /* 8000; */
	device->wfx.wBitsPerSample = bits;

	if (!device->is_out_ok){
		WAVEOUTCAPS outcaps;
		mr = waveOutGetDevCaps(WAVE_MAPPER, &outcaps, sizeof(outcaps));
		if (mr != MMSYSERR_NOERROR)
		{
			device->write_started = false;
			printf("wave out get devcaps error %d\n", mr);
			return -1;
		}
		if (device->waveOutThreadHandle == NULL){
			device->waveOutThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SpeakerThreadFun, (LPVOID)device, 0, &device->waveOutThreadId);
		}
		/*dwFlag = CALLBACK_FUNCTION;
		mr = waveOutOpen(&(device->waveoutdev), WAVE_MAPPER, &(device->wfx), (DWORD)SpeakerCallback, (DWORD)device, dwFlag);*/
		dwFlag = CALLBACK_THREAD;
		mr = waveOutOpen(&(device->waveoutdev), WAVE_MAPPER, &(device->wfx), (DWORD_PTR)device->waveOutThreadId, (DWORD)device, dwFlag);
		//	printf("mr22222222222 = %d\n",mr);
		if (mr != NOERROR)
		{
			printf("wave out open error %d\n", mr);
			return -2;
		}
		/* prepare windows buffers */
		for (i = 0; i < MAX_WAVEDHR; i++)
		{
			memset(&(device->waveouthdr[i]), 0, sizeof (device->waveouthdr[i]));
			device->waveouthdr[i].lpData = device->waveoutbuffer[i];
			device->waveouthdr[i].dwBufferLength = 320 * 10;
			device->waveouthdr[i].dwFlags = 0;
			device->waveouthdr[i].dwUser = i;

			mr = waveOutPrepareHeader(device->waveoutdev, &(device->waveouthdr[i]), sizeof (device->waveouthdr[i]));
			if (mr != MMSYSERR_NOERROR)
			{
				printf("Failed to prepare windows sound device. (waveOutPrepareHeader:0x%i)", mr);
				waveOutReset(device->waveoutdev);
				waveOutClose(device->waveoutdev);
				return -3;
			}

		}
		*minsz = device->rate / 8000 * 320;
		device->is_out_ok = true;
	}
	if (!device->is_in_ok){
		WAVEINCAPS caps;
		mr = waveInGetDevCaps(WAVE_MAPPER, &caps, sizeof (WAVEINCAPS));
		if (mr != MMSYSERR_NOERROR)
		{
			device->read_started = false;
			device->m_read_start_ok = false;
			printf("wave in get devcaps error!\n");
			return -4;
		}
		printf("caps:%d,dwFormats:%lu\n", caps.wChannels, caps.dwFormats, WAVE_FORMAT_1M08);
		if (device->waveInThreadHandle == NULL){
			device->waveInThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WaveInThreadFun, (LPVOID)device, 0, &device->waveInThreadId);
		}
		//dwFlag = CALLBACK_FUNCTION;
		////device->wfx.nChannels = 0;
		//mr = waveInOpen(&(device->waveindev), WAVE_MAPPER, &(device->wfx), (DWORD)WaveInCallback, (DWORD)device, dwFlag);
		dwFlag = CALLBACK_THREAD;
		//device->wfx.nChannels = 0;
		mr = waveInOpen(&(device->waveindev), WAVE_MAPPER, &(device->wfx), (DWORD_PTR)device->waveInThreadId, (DWORD)device, dwFlag);
		//	printf("mr1111111 = %d\n",mr);
		if (mr != NOERROR)
		{
			printf("Failed to prepare windows sound device. (waveInOpen:0x%i)1111111111111111\n", mr);
			return -5;
		}

		for (i = 0; i < MAX_WAVEDHR; i++)
		{
			memset(&(device->waveinhdr[i]), 0, sizeof (device->waveinhdr[i]));
			device->waveinhdr[i].lpData = device->waveinbuffer[i];
			device->waveinhdr[i].dwBufferLength = device->rate / 8000 * 1600;
			device->waveinhdr[i].dwFlags = 0;
			device->waveinhdr[i].dwUser = i;
			mr = waveInPrepareHeader(device->waveindev, &(device->waveinhdr[i]), sizeof(device->waveinhdr[i]));
			if (mr == MMSYSERR_NOERROR)
			{
				mr = waveInAddBuffer(device->waveindev, &(device->waveinhdr[i]), sizeof(device->waveinhdr[i]));
				if (mr != MMSYSERR_NOERROR)
				{
					printf("Failed to prepare windows sound device. (waveInAddBuffer:0x%i)22222222222222222222222", mr);
					waveInReset(device->waveindev);
					waveInClose(device->waveindev);
					return -6;
				}
			}
			else
			{
				printf("Failed to prepare windows sound device. (waveInPrepareHeader:0x%i)3333333333333333333333333", mr);
				waveInReset(device->waveindev);
				waveInClose(device->waveindev);
				return -7;
			}
		}
		mr = waveInStart(device->waveindev);
		//	printf("mr333333333= %d\n",mr);
		if (mr != MMSYSERR_NOERROR)
		{
			printf("Failed to start recording on windows sound device. (waveInStart:0x%i)4444444444444444444444444", mr);
			waveInReset(device->waveindev);
			waveInClose(device->waveindev);
			return -8;
		}
		device->is_in_ok = true;
	}
	device->m_read_start_ok=true;		
	return 0;
}

int SoundInterface::close_dev(WinSndData *device)
{
	MMRESULT mr = NOERROR;
	int i;
	int count = 0;
	if (device->waveInThreadHandle != NULL)
	{
		CloseHandle(device->waveInThreadHandle);
		device->waveInThreadHandle = NULL;
		device->waveInThreadId = 0;
	}
	if (device->is_in_ok)
	{
		/* close sound card */
		//	printf("Shutting down sound device (playing: %i) ", m_winsndData->buffer_playing);
		/* unprepare buffer */
		for (i = 0; i < MAX_WAVEDHR; i++)
		{
			int counttry = 0;
			//for (counttry = 0; counttry<10; counttry++)
			{
				mr = waveInUnprepareHeader(device->waveindev, &(device->waveinhdr[i]), sizeof (device->waveinhdr[i]));
				if (mr != MMSYSERR_NOERROR)
				{
					printf("Failed to unprepared %i buffer from sound card (waveInUnprepareHeader:0x%i\n", count, mr);
				}
				else
				{
					count++;
					break;
				}
			}
		}
		printf("unprepared %i buffer from sound card.55555555555555", count);
		mr = waveInStop(device->waveindev);
		if (mr != MMSYSERR_NOERROR)
		{
			printf("failed to stop recording sound card (waveInStop:0x%i)6666666666666666", mr);
		}
		mr = waveInReset(device->waveindev);
		if (mr != MMSYSERR_NOERROR)
		{
			printf("failed to reset recording sound card (waveInReset:0x%i)77777777777777", mr);
		}

		mr = waveInClose(device->waveindev);
		if (mr != MMSYSERR_NOERROR)
		{
			printf("failed to close recording sound card (waveInClose:0x%i)88888888888888888", mr);
		}
	}
	if (device->waveOutThreadHandle != NULL)
	{
		CloseHandle(device->waveOutThreadHandle);
		device->waveOutThreadHandle = NULL;
		device->waveInThreadId = 0;
	}
	if (device->is_out_ok){
		mr = waveOutReset(device->waveoutdev);
		if (mr != MMSYSERR_NOERROR)
		{
			printf("waveOutReset() error99999999999");
		}
		for (i = 0; i < MAX_WAVEDHR; i++)
		{
			int counttry = 0;
			//for (counttry = 0; counttry < 10; counttry++)
			{
				mr = waveOutUnprepareHeader(device->waveoutdev, &(device->waveouthdr[i]), sizeof (device->waveouthdr[i]));
				if (mr != MMSYSERR_NOERROR)
				{
					printf("Failed to unprepared %i buffer from sound card (waveOutUnprepareHeader:0x%i ", count, mr);
				}
				else
				{
					count++;
					break;
				}
			}
		}
		mr = waveOutClose(device->waveoutdev);
		if (mr != MMSYSERR_NOERROR)
		{
			//printf("waveOutClose() error");
			printf("wave out close error!\n");
		}
	}
	device->sound_err = -1;
	device->is_in_ok = false;
	device->is_out_ok = false;
	device->m_get_mutex->Lock();
	device->m_get_que->clear();
	device->m_get_mutex->Unlock();
	device->m_put_mutex->Lock();
	//device->m_put_que->clear();
	device->m_put_mutex->Unlock();
	return 0;
}

void SoundInterface::win_thread()
{
	int bsize = m_winsndData->rate/8000*320;
	uint8_t *wtmpBuff = NULL;
	
	MMRESULT mr = NOERROR;
	int pos_whdr = 0;
	m_winsndData->is_error = false;
	m_winsndData->sound_err = open_dev(m_winsndData,m_winsndData->bits,m_winsndData->stereo,m_winsndData->rate,&bsize, this);
	if (m_winsndData->sound_err != 0)
	{
		printf("open dev error %d!\n", m_winsndData->sound_err);
		m_winsndData->is_error = true;
		close_dev(m_winsndData);
		Sleep(2000);
		return;
	}
	wtmpBuff = (uint8_t*)malloc(1600);
	m_winsndData->read_stop.Lock();
	m_winsndData->write_stop.Lock();
	read_started = m_winsndData->read_started;
	write_started = m_winsndData->write_started;
	m_winsndData->write_stop.Unlock();
	m_winsndData->read_stop.Unlock();
	while(read_started||write_started)
	{
		if (m_winsndData->is_error)
		{
			printf("m_winsndData->is_error is false\n");
			break;
		}
		//printf("read_started write_started\n");
		if (m_winsndData->sound_err == 0)
		{
			if (write_started)
			{
				while(m_winsndData->buffer_playing<MAX_WAVEDHR)
				{
					/*if (isFirstPlay){
						if (m_winsndData->m_get_que->size()<30)
						{
							break;
						}
						else{
							isFirstPlay = false;
						}
					}*/
					if (m_winsndData->m_get_que->size()<10)
					{
						isFirstPlay = true;
						break;
					}
					//printf("----------------m_winsndData->m_get_que->size() = %d\n", m_winsndData->m_get_que->size());
					for (int j = 0;j<10;j++)
					{
						int t_len = 0;
						memset(wtmpBuff,0,1600);
						m_winsndData->m_get_mutex->Lock();
						if (!(m_winsndData->m_get_que->empty()))
						{
							t_len = m_winsndData->m_get_que->front().PayLoadLen;
							if (t_len == 320)
							{
								memcpy(wtmpBuff, m_winsndData->m_get_que->front().DecData, bsize);
							}
							else
							{
								memcpy(wtmpBuff,m_winsndData->m_get_que->front().DecData,1600);
							}
							m_winsndData->m_get_que->pop_front();
						}
						m_winsndData->m_get_mutex->Unlock();
						if (t_len == 320)
						{
							memcpy(m_winsndData->waveouthdr[pos_whdr].lpData+bsize*j, wtmpBuff, bsize);
						}
						else
						{
							memcpy(m_winsndData->waveouthdr[pos_whdr].lpData+1600*j, wtmpBuff, 1600);
						}
					}					
					//time_t t;
					//time(&t);
					//FILE *fp=fopen("waveout.txt","a");
					//fprintf(fp, "%s======waveOutWrite+++++++++++++++\n", ctime(&t));
					//fclose(fp);
					//printf("+++++++++++++++++++++++++");
					//printf("waveOutWrite+++++++++++++++++++++++++===========curtimestamp=%ld\n", GetTickCount());
					mr = waveOutWrite(m_winsndData->waveoutdev,&(m_winsndData->waveouthdr[pos_whdr]),sizeof(m_winsndData->waveouthdr[pos_whdr]));
					/*
					if (mr!=MMSYSERR_NOERROR)
					{
						if (mr == WAVERR_STILLPLAYING){}
					}
					else
					{
						m_winsndData->buffer_playing++;
						pos_whdr++;
						if (pos_whdr==MAX_WAVEDHR)
							pos_whdr = 0;	
					}
					*/
					if (mr == MMSYSERR_NOERROR)
					{
						m_winsndData->buffer_playing++;
						pos_whdr++;
						if (pos_whdr==MAX_WAVEDHR)
							pos_whdr = 0;
//						printf("MMSYSERR_NOERROR=======================================m_winsndData->buffer_playing=%d pos_whdr=%d\n", m_winsndData->buffer_playing,pos_whdr);
					}
					else{
						printf("!!!!!!!!!!!!!!MMSYSERR ERROR=======================================");
						//break;
					}
				}
				
				if (m_winsndData->buffer_playing==MAX_WAVEDHR)
                {
					printf("enough get data!\n");
					Sleep(10);
				}
				
				/*m_winsndData->m_get_mutex->Lock();
				if (m_winsndData->m_get_que->size()>11)
				{
					while(!(m_winsndData->m_get_que->empty()))
					{
						m_winsndData->m_get_que->pop_front();
					}
				}
				m_winsndData->m_get_mutex->Unlock();*/
				Sleep(1);
				goto END;
			}
			else
			{
				//TODO//printf("not start------------------!\n");
				m_winsndData->m_get_mutex->Lock();
				while(!(m_winsndData->m_get_que->empty()))
				{
					memcpy(wtmpBuff,m_winsndData->m_get_que->front().DecData,bsize);
					m_winsndData->m_get_que->pop_front();
				}
				m_winsndData->m_get_mutex->Unlock();
				Sleep(10);
				goto END;
			}
		}
		else 
			Sleep(10);
END:	//printf("is win_thread END\n");
		m_winsndData->read_stop.Lock();
		m_winsndData->write_stop.Lock();
//		printf("readstart22 = %d,write start = %d\n",read_started,write_started);
		read_started = m_winsndData->read_started;
		write_started = m_winsndData->write_started;
		m_winsndData->write_stop.Unlock();
		m_winsndData->read_stop.Unlock();
		//printf("is win_thread END11\n");
	    		
	}
	printf("win_thread is start!\n");
	close_dev(m_winsndData);
	printf("win_thread is end!\n");
#if 0
	if (m_winsndData->sound_err == 0)
	{
	//	printf("ttttttttttttttttttttttttt\n");
		int i;
		int count=0;
		if(m_winsndData->m_read_start_ok)
		{
			/* close sound card */
		//	printf("Shutting down sound device (playing: %i) ", m_winsndData->buffer_playing);
			/* unprepare buffer */
			for (i = 0; i < MAX_WAVEDHR; i++)
			{
				int counttry=0;
				for (counttry=0;counttry<10;counttry++)
				{
					mr = waveInUnprepareHeader(m_winsndData->waveindev,&(m_winsndData->waveinhdr[i]),sizeof (m_winsndData->waveinhdr[i]));
					if (mr != MMSYSERR_NOERROR)
					{
                    		printf("Failed to unprepared %i buffer from sound card (waveInUnprepareHeader:0x%i\n", count, mr);
					}
					else
					{
                    		count++;
							break;
					}
				}
			}			
			printf("unprepared %i buffer from sound card.55555555555555", count);
			mr = waveInStop(m_winsndData->waveindev);
			if (mr != MMSYSERR_NOERROR)
			{
				printf("failed to stop recording sound card (waveInStop:0x%i)6666666666666666", mr);
			} 	
			
			mr = waveInReset(m_winsndData->waveindev);
			if (mr != MMSYSERR_NOERROR)
			{
				printf("failed to reset recording sound card (waveInReset:0x%i)77777777777777", mr);
			} 
			
			mr = waveInClose(m_winsndData->waveindev);
			if (mr != MMSYSERR_NOERROR)
			{
				printf("failed to close recording sound card (waveInClose:0x%i)88888888888888888", mr);
			} 
		}
		mr=waveOutReset(m_winsndData->waveoutdev);
		if (mr != MMSYSERR_NOERROR)
		{
			printf("waveOutReset() error99999999999");
		}	
		for (i = 0; i < MAX_WAVEDHR; i++)
		{
			int counttry=0;
			for (counttry=0;counttry<10;counttry++)
			{
				mr = waveOutUnprepareHeader(m_winsndData->waveoutdev,&(m_winsndData->waveouthdr[i]),sizeof (m_winsndData->waveouthdr[i]));
				if (mr != MMSYSERR_NOERROR)
				{
					printf("Failed to unprepared %i buffer from sound card (waveOutUnprepareHeader:0x%i    101010101010101010", count, mr);	
				}
				else
				{
					count++;
					break;
				}
			}
		}
		mr=waveOutClose(m_winsndData->waveoutdev);
		if (mr != MMSYSERR_NOERROR)
		{
			//printf("waveOutClose() error");
			free(wtmpBuff);
			printf("wave out close error!\n");
			return ;
		}
		
			m_winsndData->sound_err=-1;
	}
#endif
	free(wtmpBuff);
	//delete m_winsndData;

	printf("end sound thread !\n");
	return;
}

int SoundInterface::SoundInterfaceStart()
{
	int ret;
	m_soundThread = new SoundThread(*this);
	if (m_soundThread == 0)
	{
		return -1;
	}
	if ((ret = m_soundThread->Start())<0)
	{
		return ret;
	}
	return ret;
}

int SoundInterface::SoundInterfaceStop()
{
	m_winsndData->read_stop.Lock();
	m_winsndData->write_stop.Lock();		
	m_winsndData->read_started = false;
	m_winsndData->write_started = false;
	m_winsndData->write_stop.Unlock();
	m_winsndData->read_stop.Unlock();
	Sleep(10);
	if (m_soundThread!=NULL)
	{
		m_soundThread->Stop();
		delete m_soundThread;
		m_soundThread = NULL;
	}
	return 0;
}

int SoundInterface::SetRead(bool flag)
{
	m_winsndData->read_stop.Lock();
	m_winsndData->read_started = flag;
	m_winsndData->read_stop.Unlock();
	return 0;
}

int SoundInterface::Play()
{
	m_winsndData->write_stop.Lock();
	if (write_started == true)
	{
		m_winsndData->write_stop.Unlock();
		return -1;
	}
	write_started = true;
	m_winsndData->write_started = true;
	m_winsndData->write_stop.Unlock();
	return 0;
}
int SoundInterface::StopPlay()
{
	m_winsndData->write_stop.Lock();
	if (write_started == false)
	{
		m_winsndData->write_stop.Unlock();
		return -1;
	}
	write_started = false;
	m_winsndData->write_started = false;
	m_winsndData->write_stop.Unlock();
	return 0;
}

int SoundInterface::SoundInterfaceReset(bool isUp)
{
	m_winsndData->write_stop.Lock();
	m_winsndData->is_error = true;
	m_winsndData->write_stop.Unlock();
	return 0;
}